package org.dftproject.lineagelinkage.core;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dftproject.genesis.data.genealogy.IPerson;

public class DuplicateManager {

	private static final Log log = LogFactory.getLog(DuplicateManager.class);

	private static final DuplicateManager singleton = new DuplicateManager();

	private final List<IDuplicateManagerListener> listeners = Collections.synchronizedList(new LinkedList<IDuplicateManagerListener>());

	private final IDuplicateRepository repository = new LocalDuplicateRepository();

	private DuplicateManager() {
	}

	/**
	 * Returns the singleton instance.
	 * @return the singleton instance
	 */
	public static DuplicateManager getDefault() {
		return singleton;
	}

	public Set<IPerson> getPrimaryPersons() {
		return repository.getPrimaryPersons();
	}

	public Set<IPerson> getPotentialDuplicates(IPerson person) {
		return repository.getPotentialDuplicates(person);
	}

	public void addPotentialDuplicate(IPerson person, IPerson duplicate) {
		repository.addPotentialDuplicate(person, duplicate);
		notifyDuplicateAdded(person, duplicate);
	}

	public void removePotentialDuplicate(IPerson person, IPerson duplicate) {
		repository.removePotentialDuplicate(person, duplicate);
		notifyDuplicateRemoved(person, duplicate);
	}

	public void addListener(IDuplicateManagerListener listener) {
		listeners.add(listener);
	}

	public void removeListener(IDuplicateManagerListener listener) {
		listeners.remove(listener);
	}

	protected void notifyDuplicateAdded(IPerson person, IPerson duplicate) {
		synchronized (listeners) {
			for (IDuplicateManagerListener listener : listeners) {
				try {
					listener.duplicateAdded(person, duplicate);
				} catch (Throwable e) {
					log.error("Error in duplicate added listener", e);
				}
			}
		}
	}

	protected void notifyDuplicateRemoved(IPerson person, IPerson duplicate) {
		synchronized (listeners) {
			for (IDuplicateManagerListener listener : listeners) {
				try {
					listener.duplicateRemoved(person, duplicate);
				} catch (Throwable e) {
					log.error("Error in duplicate removed listener", e);
				}
			}
		}
	}

	public long getDuplicateCount() {
		return repository.getDuplicateCount();
	}

}
